package advanced.io;


import java.io.*;
import java.util.Arrays;
import java.util.Comparator;

/**
 * 随机读取和写入流
 * <p>
 * 1. 文件的拆分
 * <p>
 * 2. 文件的合并
 * <p>
 * RandomAccessFile
 */
public class L_SplitFile {
    public static void main(String[] args) {
        //要拆分的文件
        String src = "";
        randomRead(src);
        //差分后的存储路径
        String destPath = "";
        spliceFile(src, destPath);
        //合并后的文件存放路径
        String tartget = "";
        combinSegment(destPath, tartget);
    }

    /**
     * 随机读取文件
     *
     * @param src
     */
    public static void randomRead(String src) {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(new File(src), "r");
            //随机读取,指定指针的位置
            //起始位置
            int beginPos = 0;
            //实际大小
            int actualSize = 1026;
            raf.seek(beginPos);
            // 读取数据
            byte[] flush = new byte[1024];
            int len = -1;
            while ((len = raf.read(flush)) != -1) {
                if (actualSize > len) {
                    //获取本次读取的所有内容
                    System.out.println(new String(flush, 0, len));
                    actualSize -= len;

                } else {
                    System.out.println(new String(flush, 0, actualSize));
                    break;
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 切分文件
     *
     * @param src
     * @param dest
     */
    public static void spliceFile(String src, String dest) {
        try {
            RandomAccessFile raf = new RandomAccessFile(new File(src), "rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //total length
        long len = src.length();
        //per size of block
        int blockSize = 1024;
        //num of blocks
        int totalBlocks = (int) Math.ceil(len * 1.0 / blockSize);

        int beginPost = 0;
        int actualSize = blockSize > len ? (int) len : (int) blockSize;
        for (int i = 0; i < totalBlocks; i++) {
            beginPost = i * blockSize;
            if (i == totalBlocks) {//最后一块
                actualSize = (int) len;
            } else {
                actualSize = blockSize;
                len -= actualSize;//计算剩余量
            }

            System.out.println(i + "块 -->" + beginPost + "-->" + actualSize);
            splice(i * blockSize, i, actualSize, src, dest);
        }


    }

    /**
     * 对文件进行切分
     *
     * @param dest 分割后的存储目标地址
     */
    private static void splice(int beginPos, int blockNo, long actualSize, String src, String dest) {
        try {

            RandomAccessFile raw = new RandomAccessFile(new File(dest + blockNo), "rw");
            RandomAccessFile raf = new RandomAccessFile(new File(src), "r");
            raw.seek(beginPos);
            //read content
            byte[] flush = new byte[1024];
            int len = -1;//the read length of per times
            while ((len = raf.read(flush)) != -1) {

                if (actualSize > len) {
                    raw.write(flush, 0, len);
                    actualSize -= len;
                } else {
                    raw.write(flush, 0, len);
                    break;
                }
            }
            raf.close();
            raw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 合并拆分后的文件
     *
     * @param srcs
     * @param target
     */
    public static void combinSegment(String srcs, String target) {
        //输出流
        try {
            OutputStream os = new BufferedOutputStream(new FileOutputStream(target, true));
            //输入流
            File[] segments = new File(srcs).listFiles();
            Comparator<File> fileComparator = new Comparator<>() {
                @Override
                public int compare(File o1, File o2) {
                    return o1.getName().compareTo(o2.getName());
                }
            };
            Arrays.sort(segments, fileComparator);//将文件按块号排序,依此拷贝
            for (File segment : segments) {
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(segment));
                //拷贝数据
                byte[] flush = new byte[1024];
                int len = -1;//接收长度
                while ((len = bis.read(flush)) != -1) {
                    os.write(flush, 0, len);//分段写出
                }
                os.flush();
                bis.close();
            }
            os.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
